Skip to content

Latest commit

 

History

History
254 lines (236 loc) · 8.05 KB

使用C语言获取DNS nameserver并进行域名解析.org

File metadata and controls

254 lines (236 loc) · 8.05 KB

使用C语言获取DNS nameserver并进行域名解析

#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>

int main()
{
  res_init();
  int i = 0;
  for (i = 0;i< _res.nscount;i++) /* _res.nscount为找到的域名服务器的数量 */
    {
      struct sockaddr_in addr = _res.nsaddr_list[i]; /* 域名服务器的地址  */
    }
  int class = C_IN;
  int type = T_A;
  unsigned char answer[512]="";
  int n =res_query("www.baidu.com", class, type, answer, sizeof(answer)); /* answer中为域名解析的结果 */
  res_close();
  for(int i=0; i<n; i++){
    printf("%02x", answer[i]);
  }
}

这种方法由于使用到了静态全局变量 _res,因此并不是线程安全的。为此glib提供了线程安全的对应函数 res_ninit, res_nquery, res_nclose:

#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>

int main()
{
  res_state res = malloc(sizeof(*res));
  res_ninit(res);
  int i = 0;
  for (i = 0;i< res->nscount;i++) /* res->nscount存储了域名服务器的个数 */
    {
      struct sockaddr_in addr = res->nsaddr_list[i]; /* 域名服务器的地址 */
    }
  int class = C_IN;
  int type = T_A;
  unsigned char answer[256]="";
  int n =res_nquery(res, "www.baidu.com", class, type, answer, sizeof(answer));  /* answer中为域名解析的结果 */
  res_nclose(res);
  for(int i=0; i<n; i++){
    printf("%02x", answer[i]);
  }
}

其中:

  • answer 中的结果是二进制格式的,不能直接解读。我们可以用python的 dnslib 库来帮忙解读
    import dnslib
    import binascii
    data=binascii.a2b_hex(answer)
    return dnslib.DNSRecord.parse(data)
        
  • res_state 的定义在 resolv/bits/types/res_state.h
    /* res_state: the global state used by the resolver stub.  */
    #define MAXNS			3	/* max # name servers we'll track */
    #define MAXDFLSRCH		3	/* # default domain levels to try */
    #define MAXDNSRCH		6	/* max # domains in search path */
    #define MAXRESOLVSORT		10	/* number of net to sort on */
    
    struct __res_state {
      int	retrans;		/* retransmition time interval */
      int	retry;			/* number of times to retransmit */
      unsigned long options;		/* option flags - see below. */
      int	nscount;		/* number of name servers */
      struct sockaddr_in
        nsaddr_list[MAXNS];	/* address of name server */
      unsigned short id;		/* current message id */
      /* 2 byte hole here.  */
      char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */
      char	defdname[256];		/* default domain (deprecated) */
      unsigned long pfcode;		/* RES_PRF_ flags - see below. */
      unsigned ndots:4;		/* threshold for initial abs. query */
      unsigned nsort:4;		/* number of elements in sort_list[] */
      unsigned ipv6_unavail:1;	/* connecting to IPv6 server failed */
      unsigned unused:23;
      struct {
        struct in_addr	addr;
        uint32_t	mask;
      } sort_list[MAXRESOLVSORT];
      /* 4 byte hole here on 64-bit architectures.  */
      void * __glibc_unused_qhook;
      void * __glibc_unused_rhook;
      int	res_h_errno;		/* last one set for this context */
      int	_vcsock;		/* PRIVATE: for res_send VC i/o */
      unsigned int _flags;		/* PRIVATE: see below */
      /* 4 byte hole here on 64-bit architectures.  */
      union {
        char	pad[52];	/* On an i386 this means 512b total. */
        struct {
          uint16_t		nscount;
          uint16_t		nsmap[MAXNS];
          int			nssocks[MAXNS];
          uint16_t		nscount6;
          uint16_t		nsinit;
          struct sockaddr_in6	*nsaddrs[MAXNS];
    #ifdef _LIBC
          unsigned long long int __glibc_extension_index
            __attribute__((packed));
    #else
          unsigned int		__glibc_reserved[2];
    #endif
        } _ext;
      } _u;
    };
    
    typedef struct __res_state *res_state;
        
  • classtype 的定义在 resolv/arpa/nameser.h
    /*%
     * Values for class field
     */
    typedef enum __ns_class {
                             ns_c_invalid = 0,	/*%< Cookie. */
                             ns_c_in = 1,		/*%< Internet. */
                             ns_c_2 = 2,		/*%< unallocated/unsupported. */
                             ns_c_chaos = 3,		/*%< MIT Chaos-net. */
                             ns_c_hs = 4,		/*%< MIT Hesiod. */
                             /* Query class values which do not appear in resource records */
                             ns_c_none = 254,	/*%< for prereq. sections in update requests */
                             ns_c_any = 255,		/*%< Wildcard match. */
                             ns_c_max = 65536
    } ns_class;
    
    typedef enum __ns_type
      {
       ns_t_invalid = 0,
    
       ns_t_a = 1,
       ns_t_ns = 2,
       ns_t_md = 3,
       ns_t_mf = 4,
       ns_t_cname = 5,
       ns_t_soa = 6,
       ns_t_mb = 7,
       ns_t_mg = 8,
       ns_t_mr = 9,
       ns_t_null = 10,
       ns_t_wks = 11,
       ns_t_ptr = 12,
       ns_t_hinfo = 13,
       ns_t_minfo = 14,
       ns_t_mx = 15,
       ns_t_txt = 16,
       ns_t_rp = 17,
       ns_t_afsdb = 18,
       ns_t_x25 = 19,
       ns_t_isdn = 20,
       ns_t_rt = 21,
       ns_t_nsap = 22,
       ns_t_nsap_ptr = 23,
       ns_t_sig = 24,
       ns_t_key = 25,
       ns_t_px = 26,
       ns_t_gpos = 27,
       ns_t_aaaa = 28,
       ns_t_loc = 29,
       ns_t_nxt = 30,
       ns_t_eid = 31,
       ns_t_nimloc = 32,
       ns_t_srv = 33,
       ns_t_atma = 34,
       ns_t_naptr = 35,
       ns_t_kx = 36,
       ns_t_cert = 37,
       ns_t_a6 = 38,
       ns_t_dname = 39,
       ns_t_sink = 40,
       ns_t_opt = 41,
       ns_t_apl = 42,
       ns_t_ds = 43,
       ns_t_sshfp = 44,
       ns_t_ipseckey = 45,
       ns_t_rrsig = 46,
       ns_t_nsec = 47,
       ns_t_dnskey = 48,
       ns_t_dhcid = 49,
       ns_t_nsec3 = 50,
       ns_t_nsec3param = 51,
       ns_t_tlsa = 52,
       ns_t_smimea = 53,
       ns_t_hip = 55,
       ns_t_ninfo = 56,
       ns_t_rkey = 57,
       ns_t_talink = 58,
       ns_t_cds = 59,
       ns_t_cdnskey = 60,
       ns_t_openpgpkey = 61,
       ns_t_csync = 62,
       ns_t_spf = 99,
       ns_t_uinfo = 100,
       ns_t_uid = 101,
       ns_t_gid = 102,
       ns_t_unspec = 103,
       ns_t_nid = 104,
       ns_t_l32 = 105,
       ns_t_l64 = 106,
       ns_t_lp = 107,
       ns_t_eui48 = 108,
       ns_t_eui64 = 109,
       ns_t_tkey = 249,
       ns_t_tsig = 250,
       ns_t_ixfr = 251,
       ns_t_axfr = 252,
       ns_t_mailb = 253,
       ns_t_maila = 254,
       ns_t_any = 255,
       ns_t_uri = 256,
       ns_t_caa = 257,
       ns_t_avc = 258,
       ns_t_ta = 32768,
       ns_t_dlv = 32769,
    
       ns_t_max = 65536
      } ns_type;
        

其他函数说明可以参见 man resolver.